/**
 * HTTP请求工具 - 基于axios，遵循苹果设计理念的简洁优雅
 */

import axios from 'axios'
import type { 
  AxiosInstance, 
  AxiosRequestConfig, 
  AxiosResponse, 
  AxiosError 
} from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useAuthStore } from '@/stores/auth'
import router from '@/router'

// 请求配置接口
interface RequestConfig extends AxiosRequestConfig {
  showLoading?: boolean
  showError?: boolean
  retry?: number
}

// 响应数据接口
interface ResponseData<T = any> {
  success: boolean
  message: string
  data: T
  total?: number
  page?: number
  size?: number
  code?: string | number
}

// 创建axios实例
const instance: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000',
  timeout: 30000,
  headers: {
    'Content-Type': 'application/json'
  }
})

// 请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 添加认证token (避免循环依赖，直接从localStorage读取)
    try {
      const token = localStorage.getItem('auth_token')
      if (token) {
        config.headers.Authorization = `Bearer ${token}`
      }
    } catch (error) {
      console.warn('无法从localStorage获取token:', error)
    }

    // 添加请求时间戳(防止缓存)
    if (config.method === 'get') {
      config.params = {
        ...config.params,
        _t: Date.now()
      }
    }

    // 显示加载提示
    const customConfig = config as RequestConfig
    if (customConfig.showLoading !== false) {
      // TODO: 显示全局loading
    }

    console.log('📤 API请求:', {
      method: config.method?.toUpperCase(),
      url: config.url,
      data: config.data,
      params: config.params
    })

    return config
  },
  (error: AxiosError) => {
    console.error('❌ 请求拦截器错误:', error)
    return Promise.reject(error)
  }
)

// 响应拦截器
instance.interceptors.response.use(
  (response: AxiosResponse<ResponseData>) => {
    // 隐藏加载提示
    // TODO: 隐藏全局loading

    const { data } = response
    
    console.log('📥 API响应:', {
      status: response.status,
      url: response.config.url,
      data: data
    })

    // 检查业务状态码
    if (data.success === false) {
      const customConfig = response.config as RequestConfig
      if (customConfig.showError !== false) {
        ElMessage.error(data.message || '请求失败')
      }
      return Promise.reject(new Error(data.message || '请求失败'))
    }

    return data
  },
  async (error: AxiosError<ResponseData>) => {
    // 隐藏加载提示
    // TODO: 隐藏全局loading

    const { response, config } = error
    const customConfig = config as RequestConfig

    console.error('❌ API响应错误:', {
      status: response?.status,
      url: config?.url,
      message: error.message,
      data: response?.data
    })

    // 处理HTTP状态码
    if (response) {
      switch (response.status) {
        case 401:
          // 未授权 - 清除token并跳转登录
          await handleUnauthorized()
          break
        case 403:
          // 无权限
          if (customConfig?.showError !== false) {
            ElMessage.error('您没有权限执行此操作')
          }
          break
        case 404:
          // 资源不存在
          if (customConfig?.showError !== false) {
            ElMessage.error('请求的资源不存在')
          }
          break
        case 422:
          // 表单验证错误
          const validationMessage = response.data?.message || '数据验证失败'
          if (customConfig?.showError !== false) {
            ElMessage.error(validationMessage)
          }
          break
        case 429:
          // 请求过于频繁
          if (customConfig?.showError !== false) {
            ElMessage.warning('请求过于频繁，请稍后再试')
          }
          break
        case 500:
          // 服务器错误
          if (customConfig?.showError !== false) {
            ElMessage.error('服务器内部错误，请联系管理员')
          }
          break
        case 502:
        case 503:
        case 504:
          // 服务不可用
          if (customConfig?.showError !== false) {
            ElMessage.error('服务暂时不可用，请稍后重试')
          }
          break
        default:
          // 其他错误
          const errorMessage = response.data?.message || `请求失败 (${response.status})`
          if (customConfig?.showError !== false) {
            ElMessage.error(errorMessage)
          }
      }
    } else if (error.code === 'ECONNABORTED') {
      // 请求超时
      if (customConfig?.showError !== false) {
        ElMessage.error('请求超时，请检查网络连接')
      }
    } else if (!window.navigator.onLine) {
      // 网络断开
      if (customConfig?.showError !== false) {
        ElMessage.error('网络连接已断开，请检查网络设置')
      }
    } else {
      // 其他网络错误
      if (customConfig?.showError !== false) {
        ElMessage.error('网络错误，请稍后重试')
      }
    }

    // 重试机制
    if (customConfig?.retry && customConfig.retry > 0) {
      customConfig.retry--
      console.log(`🔄 重试请求: ${config?.url}, 剩余重试次数: ${customConfig.retry}`)
      
      // 延迟重试
      await new Promise(resolve => setTimeout(resolve, 1000))
      return instance.request(customConfig)
    }

    return Promise.reject(error)
  }
)

// 处理未授权
async function handleUnauthorized(): Promise<void> {
  // 直接清除localStorage中的认证信息
  localStorage.removeItem('auth_token')
  localStorage.removeItem('refresh_token')
  localStorage.removeItem('user_info')
  localStorage.removeItem('user_permissions')
  localStorage.removeItem('user_roles')
  
  // 如果当前不在登录页，则跳转到登录页
  if (router.currentRoute.value.path !== '/login') {
    await ElMessageBox.confirm(
      '登录状态已过期，请重新登录',
      '会话过期',
      {
        confirmButtonText: '重新登录',
        cancelButtonText: '取消',
        type: 'warning',
        showCancelButton: false,
        closeOnClickModal: false,
        closeOnPressEscape: false
      }
    )
    
    await router.push({
      path: '/login',
      query: {
        redirect: router.currentRoute.value.fullPath
      }
    })
  }
}

// 请求方法封装
export const request = {
  /**
   * GET请求
   */
  get<T = any>(url: string, config?: RequestConfig): Promise<ResponseData<T>> {
    return instance.get(url, config)
  },

  /**
   * POST请求
   */
  post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ResponseData<T>> {
    return instance.post(url, data, config)
  },

  /**
   * PUT请求
   */
  put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ResponseData<T>> {
    return instance.put(url, data, config)
  },

  /**
   * DELETE请求
   */
  delete<T = any>(url: string, config?: RequestConfig): Promise<ResponseData<T>> {
    return instance.delete(url, config)
  },

  /**
   * PATCH请求
   */
  patch<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ResponseData<T>> {
    return instance.patch(url, data, config)
  },

  /**
   * 上传文件
   */
  upload<T = any>(url: string, file: File, config?: RequestConfig): Promise<ResponseData<T>> {
    const formData = new FormData()
    formData.append('file', file)
    
    return instance.post(url, formData, {
      ...config,
      headers: {
        'Content-Type': 'multipart/form-data',
        ...config?.headers
      }
    })
  },

  /**
   * 下载文件
   */
  async download(url: string, filename?: string, config?: RequestConfig): Promise<void> {
    try {
      const response = await instance.get(url, {
        ...config,
        responseType: 'blob'
      })

      // 创建下载链接
      const blob = new Blob([response.data])
      const downloadUrl = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = downloadUrl
      link.download = filename || 'download'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(downloadUrl)
    } catch (error) {
      console.error('文件下载失败:', error)
      ElMessage.error('文件下载失败')
    }
  },

  /**
   * 取消请求
   */
  cancelToken: axios.CancelToken,

  /**
   * 请求拦截器
   */
  interceptors: instance.interceptors
}

// 请求状态管理
export class RequestManager {
  private static pendingRequests = new Map<string, AbortController>()

  /**
   * 生成请求key
   */
  private static generateRequestKey(config: AxiosRequestConfig): string {
    return `${config.method}_${config.url}_${JSON.stringify(config.params)}`
  }

  /**
   * 添加请求
   */
  static addRequest(config: AxiosRequestConfig): void {
    const key = this.generateRequestKey(config)
    this.cancelRequest(key) // 取消相同的请求
    
    const controller = new AbortController()
    config.signal = controller.signal
    this.pendingRequests.set(key, controller)
  }

  /**
   * 移除请求
   */
  static removeRequest(config: AxiosRequestConfig): void {
    const key = this.generateRequestKey(config)
    this.pendingRequests.delete(key)
  }

  /**
   * 取消请求
   */
  static cancelRequest(key: string): void {
    const controller = this.pendingRequests.get(key)
    if (controller) {
      controller.abort()
      this.pendingRequests.delete(key)
    }
  }

  /**
   * 取消所有请求
   */
  static cancelAllRequests(): void {
    this.pendingRequests.forEach(controller => controller.abort())
    this.pendingRequests.clear()
  }
}

// 导出axios实例（用于特殊情况）
export { instance as axiosInstance }

export default request